'''
Description: 
Version: 1.0.1
Autor: hrlu.cn
Date: 2023-01-28 13:54:36
LastEditors: hrlu.cn
LastEditTime: 2023-01-28 13:56:40
'''
import os
import time
import datetime
import threading

from processor.models import Logger

class Scheduler:
    '''
    模块: 调度器
        属性:
            task_queue: 任务队列
            running_task: 运行中任务
            running_progress: 任务处理进度

            keep_running: 任务队列监听状态
        方法:
            set_timer: 开启定时任务
    '''
    task_queue = []
    running_task = []
    running_progress = 0, 1

    keep_running = False
    @classmethod
    def set_timer(cls, desp="", delay=0, itv=0, func=print, args=(), kwargs={}):
        '''
        方法: 开启定时任务
            参数: 
                delay: 任务启动时间
                    1. 传入[Int]: 于 t 秒后执行
                    2. 传入[DateTime]: 于 t 时刻执行
                deps: 任务描述
                itv: 任务循环执行间隔
                    1. 传入 0: 执行一次后退出
                    2. 传入[Int]: 执行后于 itv 天后再次执行
                func: 所需执行任务
                args: 执行任务所需参数
                kwargs: 执行任务所需键值对参数
        '''
        assert isinstance(delay, int) or isinstance(delay, datetime.datetime), "Scheduler.set_timer needs int or datetime type of value."
        assert isinstance(desp, str), "Scheduler.set_timer needs string type of value."
        if isinstance(delay, int): delay = datetime.datetime.now() + datetime.timedelta(seconds=delay)

        cls.task_queue.append([delay, desp, itv, func, args, kwargs])
        cls.task_queue.sort(key = lambda x: x[0])
        
        if not cls.keep_running:
            cls.keep_running = True
            threading.Thread(target = Scheduler.start_work, ).start()

    @classmethod
    def start_work(cls):
        '''
        方法: 开始处理定时任务
        '''
        while cls.keep_running:
            if cls.task_queue and cls.task_queue[0][0] < datetime.datetime.now():
                t, desp, itv, func, args, kwargs = cls.task_queue.pop(0)

                cls.running_task.append([desp, datetime.datetime.strftime(datetime.datetime.now(), r'%Y-%m-%d %H:%M:%S')])
                Logger.info(msg=f"定时任务: {desp} 已启动。", module='scheduler')
                
                try:
                    func(*args, **kwargs)
                    Logger.info(msg=f"定时任务: {desp} 执行完毕。", module='scheduler')
                except Exception as e:
                    Logger.error(msg=f"定时任务: {desp} 执行错误。 {e}", module='scheduler')
                
                cls.running_task.pop()
                cls.running_progress = 0, 1

                if itv != 0 and isinstance(itv, int):
                    cls.task_queue.append([t + datetime.timedelta(days = itv), desp, itv, func, args, kwargs])
                    cls.task_queue.sort(key = lambda x: x[0])
            elif not cls.task_queue:
                cls.keep_running = False
            time.sleep(1)

    @classmethod
    def update_progress(cls, *pgs):
        cls.running_progress = pgs